﻿#include<stdio.h>
#include<conio.h>
#include<dos.h>
#include<time.h>

#define DOWN 0x5000
#define UP 0x4800
#define ENTER 0x1c0d

#define N 11
#define DATESIZE sizeof(struct _date)

char myname[N];                                     /***存放本次操作的文件名***/

int flag1=1;                                        /****登陆菜单的循环控制***/


struct _date                                        /***账目部分结构体1**/
{
    int year;
    int mon;
    int mday;
};


struct account                                       /***账目部分结构体1**/
{
           struct _date mydate;
           char io[4];
           float  money;
           char  remark[40];
           struct account *next;
};


void mytitle()                                       /***头部显示***/
{

        textmode(C80);
        textbackground(1);
        textcolor(13);
        clrscr();
        gotoxy(17,5);
        cprintf("*******Welcome to Michael Account v2.0*******\n");

        gotoxy(17,7);
        cprintf("Please tell Michael the Bug during your using\n");

        gotoxy(17,9);
        cprintf("***********Copyright@Michael******************\n");

        gotoxy(17,11);
        cprintf("**********E-mail: yxc023@qq.com*****************\n");
        getch();
        clrscr();

}


void upbar(int x,int y,int endx)                        /***上移光条函数***/
{
        int i;
        typedef struct texel_struct{
                 char ch;
                 char attr;
        }texel;
        texel t;

        for(i=x;i<=endx;i++)
        {
             gettext(i,y,i,y,&t);
             t.attr=15+(1<<4);                     /****恢复蓝底白字*****/
             puttext(i,y,i,y,&t);

             gettext(i,y-2,i,y-2,&t);
             t.attr=0+(7<<4);                      /****光条灰底黑字*****/
             puttext(i,y-2,i,y-2,&t);
        }
}


void downbar(int x,int y,int endx)                    /***下移光条函数***/
{
        int i;
        typedef struct texel_struct{
                 char ch;
                 char attr;
        }texel;
        texel t;

        for(i=x;i<=endx;i++)
        {
             gettext(i,y,i,y,&t);
             t.attr=15+(1<<4);
             puttext(i,y,i,y,&t);

             gettext(i,y+2,i,y+2,&t);
             t.attr=0+(7<<4);
             puttext(i,y+2,i,y+2,&t);
        }
}


int login_interface()                                 /**登陆界面函数**/
{
     int key;
     int num=1;

     textcolor(WHITE);
     clrscr();

     gotoxy(17,5);
     cprintf("login");

     gotoxy(17,7);
     cprintf("register");

     gotoxy(17,9);
     cprintf("exit");

     upbar(17,7,27);

     do
     {
        key=bioskey(0);
        switch(key)
        {
           case DOWN:switch(num)
                     {
                         case 1: downbar(17,5,27);num++;break;
                         case 2: downbar(17,7,27);num++;break;
                     }
                     break;

           case UP: switch(num)
                    {
                         case 3: upbar(17,9,27);num--;break;
                         case 2: upbar(17,7,27);num--;break;
                    }
                    break;
        }
     }while(key!=ENTER);
     return num;
}


void login()                                                 /**用户登陆函数***/
{
      char name[N]="'\0'",passwd[N]="'\0'",filepasswd[N]="'\0'";
      int i=0;
      char c;
      FILE *fp;

      gotoxy(17,12);
      cprintf("     Name       :");
      gotoxy(17,13);
      cprintf("   Password     :");
      gotoxy(35,12);
      gets(name);
      gotoxy(35,13);
      while((c=getch())!=13)
      {
         passwd[i]=c;
         cprintf("*");
      }
      gotoxy(30,15);

      if((fp=fopen(name,"rb+"))==NULL)
          {
                 cprintf("Name does not exist!");
          }
      fread(filepasswd,sizeof(passwd),1,fp);
      if(strcmp(passwd,filepasswd)==0)
          {
                   flag1=0;
                   fclose(fp);
                   cprintf("login succeesfully!");
                   getch();

          }
      else  {
             cprintf("password wrong!");
             getch();
             }

      strcpy(myname,name);
}


void creat()                                             /**用户创建函数***/
{
      char name[N]="'\0'";
      char passwd[N]="'\0'",repasswd[N]="'\0'";
      char c;
      int i;
      FILE *_newfile;

      gotoxy(17,12);
      cprintf("     Name       :");
      gotoxy(17,13);
      cprintf("  New Password  :");
      gotoxy(17,14);
      cprintf(" Again Password :");
      gotoxy(35,12);
      gets(name);
      gotoxy(35,13);
      i=0;
      while((c=getch())!=13)
      {
         passwd[i]=c;
         cprintf("*");
      }
      gotoxy(35,14);
      i=0;
      while((c=getch())!=13)
      {
         repasswd[i]=c;
         cprintf("*");
      }
      gotoxy(30,15);
      if(strcmp(passwd,repasswd)==0)
         {

             _newfile=fopen(name,"wb+");

             fwrite(passwd,sizeof(passwd),1,_newfile);
             fwrite(name,sizeof(name),1,_newfile);

             fclose(_newfile);
             printf("register succeesfully");
             getch();
             flag1=0;
         }
      else {
            printf("passwords are diffirent!");
            getch();
            }
     strcpy(myname,name);
}


int new_interface()                                    /***操作菜单界面***/
{
    int num;
    int key;

    window(1,2,25,15);
    textbackground(1);
    clrscr();

    gotoxy(1,1);
    cprintf("add accound");
    gotoxy(1,3);
    cprintf("delete accound");
    gotoxy(1,5);
    cprintf("edit accound");
    gotoxy(1,7);
    cprintf("compile accound");
    gotoxy(1,9);
    cprintf("exit");

    upbar(1,4,18);
    num=1;

    do
     {
        key=bioskey(0);

        switch(key)
        {
           case DOWN:switch(num)
                     {
                         case 1: downbar(1,2,18);num++;break;
                         case 2: downbar(1,4,18);num++;break;
                         case 3: downbar(1,6,18);num++;break;
                         case 4: downbar(1,8,18);num++;break;
                     }
                     break;

           case UP: switch(num)
                    {
                         case 5: upbar(1,10,18);num--;break;
                         case 4: upbar(1,8,18);num--;break;
                         case 3: upbar(1,6,18);num--;break;
                         case 2: upbar(1,4,18);num--;break;
                    }
                    break;
        }
     }while(key!=ENTER);
     return num;
}


struct account *getdata()                                /***从文件中取得数据的函数***/
{
        struct account *p2,*p1;
        struct account *head;

        FILE *fp;
        int n=0;

        fp=fopen(myname,"rb+");

        fseek(fp,22,0);

        p1=(struct account *)malloc(sizeof(struct account));

        head=NULL;
        while (1)
        {
               n=n+1;
               if(n==1) head=p1; 
               else p2->next=p1;
               
               if(fread(&p1->mydate,DATESIZE,1,fp)==0) 
               {
   
                   if(n==1) head=NULL;
                   free(p1);
                   p2->next=NULL;
                   break;
               }

               fread(p1->io,sizeof(p1->io),1,fp);
               fread(&p1->money,sizeof(float),1,fp);
               fread(p1->remark,sizeof(p1->remark),1,fp);

               p2=p1;
               p1=(struct account *)malloc(sizeof(struct account));
        }
        return head;
}


void print_act(struct account *head)                    /***数据显示函数****/
{
   struct account *p1;
   int num=0;

   p1=head;

   window(30,1,80,25);
   textbackground(1);
   clrscr();
   printf(" NO.      date   in/out  money  remark");
   gotoxy(1,2);
   while(p1!=NULL)
             {
                         num++;
                         if(num%21==0)       /***每输出20个清一次屏****/
                         {
                            printf("press any key to show next 20");
                            getch(); 
                            window(30,1,80,25);
                            textbackground(1);
                            clrscr();
                            printf(" NO.      date   in/out  money  remark");
                            gotoxy(1,2);
                               
                         }
                         printf("%04d  %d/%02d/%02d   %s   %.2f     %s",num,p1->mydate.year,p1->mydate.mon,
                                                               p1->mydate.mday,p1->io,p1->money,p1->remark);
                         p1=p1->next;
                         gotoxy(1,num%21+2);
             }

}


struct account *realadd(struct account *head,struct account *p1)           /***账目添加插入链表函数****/
{
    int transdateA,transdateB,_end=1;
    struct account *p2;
                    
          p2=head;
          if(p2==NULL) {
                                            head=p1;
                                            p1->next=NULL;

                         } 
          else {
                         
                         transdateA=10000*p1->mydate.year+100*p1->mydate.mon+p1->mydate.mday;
                         while (_end==1)
                         {
                               transdateB=10000*p2->mydate.year+100*p2->mydate.mon+p2->mydate.mday;  
                               if(transdateA>=transdateB)
                             {
                                      if(p2->next==NULL || transdateA<10000*p2->next->mydate.year+100*p2->next->mydate.mon+p2->next->mydate.mday)
                                     {
                                             p1->next=p2->next;
                                             p2->next=p1;
                                             _end=0;
                                      }
                               }
                               else {head=p1;p1->next=p2;_end=0;}
                               p2=p2->next;
                         }
                 }
            return head;
}


void save(struct account *head)                             /****保存函数****/
{
         char passwd[N]="'\0'";
         struct account *p1;
         FILE *fp;

         if((fp=fopen(myname,"rb+"))==NULL)
         {
                printf("NULL");
         }
         fread(passwd,sizeof(passwd),1,fp);
         fclose(fp);
         fp=fopen(myname,"wb+");
         fwrite(passwd,sizeof(passwd),1,fp);
         fwrite(myname,sizeof(myname),1,fp);

         p1=head;
         while (p1!=NULL)
         {
                fwrite(&p1->mydate,DATESIZE,1,fp);
                fwrite(p1->io,sizeof(p1->io),1,fp);
                fwrite(&p1->money,sizeof(float),1,fp);
                fwrite(p1->remark,sizeof(p1->remark),1,fp);
                free(p1);
                p1=p1->next;
         }
         fclose(fp);
}


void accountadd(int num,struct account *head)                /***账目添加新建结点函数****/
{
       
       struct account *p1;
       char in[4]={"in "},out[4]={"out"};
       char queren;
       float money;
       int x,y;

       p1=(struct account *)malloc(sizeof(struct account));

       if(num==1) strcpy(p1->io,in);
       else strcpy(p1->io,out);

       gotoxy(8,1);
       printf("date  :");
       gotoxy(8,2);
       printf("money :");
       gotoxy(8,3);
       printf("remark:");

       gotoxy(15,1);
       
       scanf("%d/%d/%d",&p1->mydate.year,
                        &p1->mydate.mon,
                        &p1->mydate.mday
                );
       gotoxy(15,2);
       scanf("%f",&money);
       getchar();
       p1->money=money;
       gotoxy(15,3);
       memset(p1->remark,0,39);
       gets(p1->remark);
       gotoxy(8,5);
       printf("add?(y/n):");
       scanf("%c",&queren);
       gotoxy(15,6);
       switch (queren)
       {
       case 'y':head=realadd(head,p1);save(head);break;
       case 'n': printf("wrong!");free(p1);break;
       default: printf("wrong!!");free(p1);

       }
}


void menuadd(struct account *head)                   /***账目添加菜单函数*****/
{
         int num,key;
         window(1,16,25,25);
         textbackground(1);
         clrscr();

         gotoxy(2,1);
         cprintf("in");
         gotoxy(2,3);
         cprintf("out");
         gotoxy(2,5);
         cprintf("back");
          num=1;
         upbar(2,18,6);
         do
         {
             key=bioskey(0);
             switch(key)
            {
                case DOWN:switch(num)
                     {
                         case 1: downbar(2,16,6);num++;break;
                         case 2: downbar(2,18,6);num++;break;
                     }
                     break;

                   case UP: switch(num)
                    {
                         case 3: upbar(2,20,6);num--;break;
                         case 2: upbar(2,18,6);num--;break;
                    }
                    break;
               }
         }while(key!=ENTER);
         gotoxy(2,6);

         switch (num)
         {
         case 1: accountadd(1,head);break;
         case 2: accountadd(2,head);break;
         case 3: return ;
         default: printf("wrong!");
         }
}


void todayis()                                           /***顶部日期显示函数****/
{
    time_t timep;
    struct tm *pt;
    time(&timep);
    pt=localtime(&timep);
    window(1,1,20,1);
    textbackground(1);
    clrscr();
    printf("today is: <%d/%02d/%02d>",(1900+pt->tm_year),(1+pt->tm_mon),pt->tm_mday);
}


struct account *onedel(struct account *head)               /****单一账目结点删除函数****/
{
     int num,n=1;
            int flag_n=1;
            struct account *p1,*p2;
            p1=head;

            gotoxy(1,7);
            cprintf("which NO.to be deleted:");
            gotoxy(24,7);

            scanf("%d",&num);
            while(flag_n)
             {
                       if(num==1)
                           {
                                    head=p1->next;
                                    flag_n=0;
                            
                            }
                      else{
                       
                                           n++;
                                           if(num==n)
                                           {
                                                 p2=p1;
                                                 p1=p1->next;
                                                 p2->next=p1->next;
                                                 flag_n=0;
                       
                                            }
                                            p1=p1->next;
                            }
             }
             save(head);
             return head;
}


struct account *daydel(struct account *head)            /***单日账目结点删除函数*****/
{
      int year,mon,mday;
      struct account *p1,*p2;
      p1=head;

            gotoxy(1,7);
            cprintf("which day to delete:");
            gotoxy(1,8);
            scanf("%d/%d/%d",&year,&mon,&mday);
    
            while(p1!=NULL&&(10000*year+100*mon+mday)<=(10000*p1->mydate.year+100*p1->mydate.mon+p1->mydate.mday))
              {
                         
                         if (p1->mydate.year==year&&p1->mydate.mon==mon&&p1->mydate.mday==mday)
                          {
                                    
                                    if(p1==head)
                                   {
                                                head=p1->next;
                                                p1=p1->next;
                                   }
                                   else 
                                    {
                                              p2->next=p1->next;
                                              p1=p1->next;
                                   
                                   }
                           }
                           else 
                          {
                                 p2=p1;
                                 p1=p1->next;  
                           }
                         
              }
             save(head);
             return head;
}


void menudel(struct account *head)                    /****账目删除菜单函数****/
{
        int num=1,key;
        window(1,16,25,25);
        textbackground(1);
        clrscr();

         gotoxy(2,1);
         cprintf("delete single account");
         gotoxy(2,3);
         cprintf("delete oneday account");
         gotoxy(2,5);
         cprintf("back");
         upbar(2,18,23);

         do
         {
             key=bioskey(0);
             switch(key)
            {
                case DOWN:switch(num)
                     {
                         case 1: downbar(2,16,23);num++;break;
                         case 2: downbar(2,18,23);num++;break;
                     }
                     break;

                   case UP: switch(num)
                    {
                         case 3: upbar(2,20,23);num--;break;
                         case 2: upbar(2,18,23);num--;break;
                    }
                    break;
               }
         }while(key!=ENTER);


        switch (num)
        {
        case 1: head=onedel(head);break;
        case 2: head=daydel(head);break;
        case 3: break;
        default:printf("wrong!!\n");
        }
}

void realedit(struct account *p1)                       /****结点账目编辑函数*****/
{
        int num1,num2;
        char in[4]={"in "},out[4]={"out"};
        int num=1,key;

        gotoxy(2,2);
        cprintf("date  ");
        gotoxy(2,4);
        cprintf("in/out");
        gotoxy(2,6);
        cprintf("money ");
        gotoxy(2,8);
        cprintf("remark");
        gotoxy(2,10);
        cprintf("back  ");

        upbar(2,19,10);

        do
         {
             key=bioskey(0);
             switch(key)
            {
                case DOWN:switch(num)
                     {
                         case 1: downbar(2,17,10);num++;break;
                         case 2: downbar(2,19,10);num++;break;
                         case 3: downbar(2,21,10);num++;break;
                         case 4: downbar(2,23,10);num++;break;

                     }
                     break;

                   case UP: switch(num)
                    {
                         case 5: upbar(2,25,10);num--;break;
                         case 4: upbar(2,23,10);num--;break;
                         case 3: upbar(2,21,10);num--;break;
                         case 2: upbar(2,19,10);num--;break;
                    }
                    break;
               }
         }while(key!=ENTER);

         switch (num)
         {
         case 1:gotoxy(11,2);printf(":");
                scanf("%d/%d/%d",&p1->mydate.year,&p1->mydate.mon,&p1->mydate.mday);
                break;
         case 2:gotoxy(11,4);
                printf("1=in,2=out:");scanf("%d",&num2);
                     switch (num2)
                     {
                     case 1: strcpy(p1->io,in);break;
                     case 2: strcpy(p1->io,out);break;
                     default:printf("wrong!");
                     }
                     break;
         case 3:gotoxy(11,6);printf(":");
                scanf("%f",&p1->money);break;
         case 4:gotoxy(11,8);printf(":");
                getchar();gets(p1->remark);break;
         case 5:break;
         }

}

void menuedt(struct account *head)                        /****账目编辑菜单函数****/
{
        int num,n=1;
        int flag_n=1;
        struct account *p1;

        window(1,16,25,25);
        textbackground(1);
        clrscr();

        gotoxy(2,1);
        printf("which NO.to edit:");
        scanf("%d",&num);

        p1=head;

        while(flag_n)
             {
                       if(num==n)
                         {
                                    realedit(p1);
                                    flag_n=0;
                         }
                         n++;
                         p1=p1->next;
             }
             save(head);
}

void statistics1(struct account *head)                             /******总体统计函数*******/
{
        struct account *p1;
        float all_in=0,all_out=0;
        p1=head;
        while (p1!=NULL)
        {
                if (strcmp(p1->io,"in ")==0) all_in+=p1->money;
                else all_out+=p1->money;
                p1=p1->next;         
        }
        gotoxy(1,1);
        cprintf("all account statistics:");
        gotoxy(1,2);
        cprintf("all in  :%.2f",all_in);
        gotoxy(1,3);
        cprintf("all out :%.2f",all_out);
        gotoxy(1,4);
        cprintf("leavings:%.2f\n",all_in-all_out);
}

void statistics2(head)                             /***区间统计函数****/
{
         time_t start,end;
         struct date d1,d2;
         struct time t;
         int mon;
         long second,min,hour,day;
         int flag_s=1;
         float in=0,out=0;

         struct account *p1;
         int transdateA,transdateB,transdate;
         
         gotoxy(1,6);
         printf("start day:");
         gotoxy(1,7);
         printf("end day  :");
         gotoxy(12,6);
         scanf("%d/%d/%d",&d1.da_year,&mon,&d1.da_day);
         d1.da_mon=mon;
         gotoxy(12,7);
         scanf("%d/%d/%d",&d2.da_year,&mon,&d2.da_day);
         d2.da_mon=mon;

         transdateA=10000*d1.da_year+100*d1.da_mon+d1.da_day;
         transdateB=10000*d2.da_year+100*d2.da_mon+d2.da_day;


         t.ti_hour=0;
         t.ti_min=0;
         t.ti_sec=0;
         start=dostounix(&d1,&t);
         end=dostounix(&d2,&t);

         second=end-start;
         min=second/60;
         hour=min/60;
         day=hour/24;
         
         p1=head;
         while(p1!=NULL&&flag_s)
       { 
                 transdate=10000*p1->mydate.year+100*p1->mydate.mon+p1->mydate.mday;
                 if (transdate>=transdateA&&transdate<=transdateB)
                 {
                           if (strcmp(p1->io,"in ")==0)  in+=p1->money;
                           else out+=p1->money;

                 }
                  if (transdate>transdateB) flag_s=0;
                  p1=p1->next;       
        }
        gotoxy(1,8);
        printf("day:%ld\nin/day:%.2f\nout/day:%.2f",day+1,in/(day+1),out/(day+1));

}

void menusta(head)                                /****账目统计菜单函数****/
{
   window(1,16,25,25);
   textbackground(1);
   clrscr();
   statistics1(head);
   statistics2(head);
}


int main()
{
    struct account *head;
    mytitle();
    while(flag1)
    {
            switch(login_interface())
           {
                case 1: login();break;
                case 2: creat();break;
                case 3: return 0;
           }
     }
    clrscr();
    while(1)
     {
         todayis();
         head=getdata();
         print_act(head);
         switch(new_interface())
         {
            case 1: menuadd(head);break;
            case 2: menudel(head);break;
            case 3: menuedt(head);break;
            case 4: menusta(head);break;
            case 5: return 0;
         }
      }
}


